#*************************###
"""                       ###
    本文件用于读取nc、hdf文件
    对图像进行裁切等基本操作
"""                       ###
#*************************###
import os

import netCDF4
import numpy as np
import scipy.misc as misc
import cv2
import matplotlib.pyplot as plt

HDF5_USE_FILE_LOCKING = False

def read_rs(in_file):
    """
    读取遥感原始文件并将所需通道信息保存在一个字典中
    :param in_file: 输入文件路径
    :return: rs_info 存有通道信息的字典
    """
    with netCDF4.Dataset(in_file) as nf:
        rs_info = {}
        rs_info['albedo_01'] = nf.variables["albedo_01"][:].data
        m = np.max(rs_info['albedo_01'])
        rs_info['albedo_01']=rs_info['albedo_01']/m*255
        rs_info['albedo_02'] = nf.variables["albedo_02"][:].data/m*255
        rs_info['albedo_03'] = nf.variables["albedo_03"][:].data/m*255
        rs_info['albedo_04'] = nf.variables["albedo_04"][:].data/m*255
        rs_info['albedo_05'] = nf.variables["albedo_05"][:].data/m*255
    return rs_info

def read_cld(in_file):
    """
    读取云产品中的类别信息，并将其返回
    :param in_file: 输入文件路径
    :return: cld_type 存有云类别信息的ndarray
    """
    with netCDF4.Dataset(in_file) as nf:
        cld_type = nf.variables["CLTYPE"][:].data
    return cld_type

def cld_dye(cld_type):
    """
    根据云类别信息（W*H）将区域染色并将最后的掩膜（W*H*3）返回
    :param cld_type:云类别信息（ndarray）
    :return:掩膜(openCV图像)
    """

    '''颜色索引'''
    color_index = np.array([[0x00, 0x00, 0x00],  # 黑色     无云
                   [0xc6, 0xcf, 0xd0],  # 淡蓝灰   卷云
                   [0x8f, 0xad, 0x80],  # 蓝灰     卷积云
                   [0xea, 0xbc, 0x8d],  # 淡稻黄    深对流
                   [0xdb, 0x90, 0x53],  # 稻黄     高积云
                   [0x6f, 0x5d, 0x27],  # 熟绿     高层云
                   [0xf2, 0xa4, 0x90],  # 嫩粉色    雨层云
                   [0xb8, 0x42, 0x4d],  # 牛血红    积云
                   [0x95, 0x95, 0xb1],  # 浅紫      层积云
                   [0xd4, 0x6c, 0x4e],  # 橙红      层云
                   [0xca, 0xbc, 0xb2],  # 浅褐色    未知
                   [0xff, 0xff, 0xff]  # 白色      无数据
                   ])
    # RGB -> BRG
    color_index = color_index[:, [2, 1, 0]]

    mask = np.zeros((cld_type.shape[0],cld_type.shape[1],3))
    for t in range(11):
        mask[np.where(cld_type==t)]=color_index[t]
    mask[np.where(cld_type==255)] = color_index[11]
    mask = mask.transpose(2,0,1)

    mask_out = cv2.merge((mask[0],mask[1],mask[2]))

    return mask_out

def crop_img_save(input_img,out_dir,name="defaultImg",valid_thd=0.3,cld=None,w=1000,h=1000,step=200):
    """
    传入一幅（openCv）图像将其根据对应的cld标记裁剪（无数据部分不超过某个阈值），
    并保存成png图像
    :param input_img: 输入的（opencv）图像
    :param out_dir: 输出的目录
    :param name: 裁剪图像的名称
    :param valid_thd: 该切块无效的阈值
    :param cld: 用于标记类别的ndarray
    :param w: 目标图像的宽
    :param h: 目标图像的高
    :param step: 裁剪图像距离的步数
    :return: None
    """

    #判断路径是否存在，若不存在则新建
    if not os.path.exists(out_dir):
        os.makedirs(out_dir)

    #遍历裁剪
    for i in range(0,input_img.shape[1]-h-1,step):
        for j in range(0,input_img.shape[0]-w-1,step):

            #若类别标记不为空则考虑
            if cld is not None:
                cld_cropped = cld[j:j+w,i:i+h]
                no_data = np.extract(cld_cropped>200,cld_cropped)

                if(no_data.size>h*w*valid_thd):
                    continue

            print(i, j)
            img_cropped = input_img[j:j+w,i:i+h]
            cv2.imwrite(out_dir+"/"+name+'_%02d_%02d.png' % (i,j), img_cropped)

def save_img(img, out_dir, name="default"):

    # 判断路径是否存在，若不存在则新建
    if not os.path.exists(out_dir):
        os.makedirs(out_dir)

    cv2.imwrite(out_dir + "/" + name + '.png', img)

def ndarrdy_to_img(channels,output_dir,output_name):
    """
    TODO: 将ndarray转换成cv2的图像
    注意cv2里面的图像是BGR的，要注意把通道转换一下
    :param channels:
    :param output_dir:
    :param output_name:
    :return:
    """
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
    img = cv2.merge((channels[0],channels[1],channels[2]))
    cv2.imwrite(output_dir+'/'+output_name,img)

def display_legend():
    """
    显示并写入图例
    :return:None
    """
    color_index = np.array([[0x00, 0x00, 0x00],  # 黑色     无云
                       [0xc6, 0xcf, 0xd0],  # 淡蓝灰   卷云
                       [0x8f, 0xad, 0x80],  # 蓝灰     卷积云
                       [0xea, 0xbc, 0x8d],  # 淡稻黄    深对流
                       [0xdb, 0x90, 0x53],  # 稻黄     高积云
                       [0x6f, 0x5d, 0x27],  # 熟绿     高层云
                       [0xf2, 0xa4, 0x90],  # 嫩粉色    雨层云
                       [0xb8, 0x42, 0x4d],  # 牛血红    积云
                       [0x95, 0x95, 0xb1],  # 浅紫      层积云
                       [0xd4, 0x6c, 0x4e],  # 橙红      层云
                       [0xca, 0xbc, 0xb2],  # 浅褐色    未知
                       [0xff, 0xff, 0xff]  # 白色      无数据
                       ])
    #RGB -> BRG
    color_index = color_index[:,[2,1,0]]

    text = ['Clr','Ci','Cs','DC','Ac','As','Ns','Cu','Sc','St','NK','ND']



    img = np.zeros((720,100,3))
    for i in range(12):
        img[i * 60:(i + 1)*60, :, :] = color_index[i]
        font = cv2.FONT_HERSHEY_SIMPLEX
        if i==0:
            cv2.putText(img, text[i], (5, i * 60 + 35), font, 1, (255, 255, 255), 2, cv2.LINE_AA)
        else:
            cv2.putText(img,text[i],(5,i*60+35),font,1,(0,0,0),2,cv2.LINE_AA)

    #img = cv2.merge((a[0],a[1],a[2]))
    cv2.imshow('1',img)
    cv2.imwrite('1.png',img)
    cv2.waitKey()

def cal_ratio(patch):
    """
    TODO: 计算在每个patch中各云种占画面的比例
    :param patch:
    :return:
    """
    total_num = patch.shape[0]*patch.shape[1]
    num_list = np.bincount(patch.astype(np.int64).flatten())
    num_list = num_list/total_num
    return num_list[1:10]

def count_elm(lst,elm):
    """
    返回一个列表中某元素出现的次数
    :param lst: 列表
    :param elm: 待求元素
    :return: 某元素出现的次数
    """
    cnt = 0
    for i in range(lst.size):
        if lst[i]==elm:
            cnt+=1
    return cnt

def label_s(patch,thr=0.3):
    """
    对某个patch对应的云种打单标签
    :param patch: 传入的云分类patch
    :param thr: 阈值
    :return: 经过编码的标签（一个数组，有标签为1）
    """
    ratios = cal_ratio(patch)
    encoded = np.zeros_like(ratios)
    m = np.max(ratios)
    if m>thr and count_elm(ratios,m)==1:
        encoded[np.where(ratios==m)] = 1

    return encoded

def label_m(patch,thr=0.05):
    """
    对某个patch对应的云种打多标签
    :param patch: 传入的云分类patch
    :param thr: 阈值
    :return: 经过编码的标签（一个数组，有标签为1）
    """
    ratios = cal_ratio(patch)
    encoded = np.zeros_like(ratios)
    encoded[ratios>thr] = 1
    return encoded

def more_cloud(patch):
    total_num = patch.shape[0] * patch.shape[1]
    num_list = np.bincount(patch.astype(np.int64).flatten())
    num_list = num_list / total_num
    if np.sum(num_list[1:10])>0.5:
        return True
    else :
        return False


#if __name__ == 'main':





